#pragma once
#include "../smart_ptr/smart_ptr.hpp"
#include "../parallel/thread.hpp"
#include <type_traits>

namespace umtl
{
	//////////////////////////////////////////////////////////////////////////
	//

	template< typename value_type, typename mutex_type = umtl::parallel::critical_section >
	class atomic
	{
	public:
		typedef value_type					value_type;
		typedef mutex_type					mutex_type;

		struct mutex_locker
		{
			mutex_locker( mutex_type& m ) : m_(m)	{ m_.enter(); }
			~mutex_locker()							{ m_.leave(); }
			mutex_type& m_;
		};

		atomic() {}
		virtual ~atomic() {}

		template< typename Accessor >
		void access( Accessor const accessor ) const { mutex_locker locker(mutex_); accessor(value_); }

		template< typename Accessor >
		void access( Accessor accessor ) { mutex_locker locker(mutex_); accessor(value_); }

	private:
		mutex_type mutex_;
		value_type value_;

		atomic(atomic const&);
		void operator=(atomic const&);
	};

	//////////////////////////////////////////////////////////////////////////
}